package hydrap2p.hubmanager;


import hydrap2p.ServiceLocation;
import hydrap2p.helper.Pinger;
import hydrap2p.hub.HubStatus;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Listeners {

	private final List<Listener> listeners;
	private final List<MyPinger> pingers;
	
	public Listeners()
	{
		listeners = new LinkedList<Listener>();
		pingers = new LinkedList<MyPinger>();
	}

	public void addListener(Map<String, ServiceLocation> protocols, Map<String, HubStatus> statuses, Listener listener)
	{
		synchronized(listeners)
		{
			if (!listeners.contains(listener))
			{
				ListenerQueue temp=new ListenerQueue(this, listener);
				
				// sync up to current status
				synchronized(protocols)
				{
					synchronized(statuses)
					{
						for (String protocol : protocols.keySet())
							temp.protocolRegistered(protocol);
						for (HubStatus status : statuses.values())
							temp.connectionAdded(status);
						
						listeners.add(temp);
						if (listener instanceof ThriftListener)
						{
							ServiceLocation location = ((ThriftListener)listener).getLocation();
							MyPinger pinger = new MyPinger(location.address+":"+location.port,location);
							pingers.add(pinger);
							
						}
					}
				}
			}
			
		}
	}
	public void delListener(Listener listener)
	{
		synchronized(listeners)
		{
			listeners.remove(listener);
		}
		listener.stop();
	}
	
	public void connectionAdded(HubStatus status) {
		synchronized(listeners)
		{
			for (Listener listener : listeners)
			{
				try {
					listener.connectionAdded(status);
				} catch (Exception e) {
					delListener(listener);
				}
			}
		}
	}

	public void connectionChanged(HubStatus status) {
		synchronized(listeners)
		{
			for (Listener listener : listeners)
			{
				try {
					listener.connectionChanged(status);
				} catch (Exception e) {
					delListener(listener);
				}
			}
		}
	}

	public void connectionRemoved(HubStatus status) {
		synchronized(listeners)
		{
			for (Listener listener : listeners)
			{
				try {
					listener.connectionRemoved(status);
				} catch (Exception e) {
					delListener(listener);
				}
			}
		}
	}

	public void connectionConnected(HubStatus status) {
		synchronized(listeners)
		{
			for (Listener listener : listeners)
			{
				try {
					listener.connectionConnected(status);
				} catch (Exception e) {
					delListener(listener);
				}
			}
		}
	}

	public void protocolRegistered(String name) {
		synchronized(listeners)
		{
			for (Listener listener : listeners)
			{
				try {
					listener.protocolRegistered(name);
				} catch (Exception e) {
					delListener(listener);
				}
			}
		}
	}

	public void protocolUnregistered(String name) {
		synchronized(listeners)
		{
			for (Listener listener : listeners)
			{
				try {
					listener.protocolUnregistered(name);
				} catch (Exception e) {
					delListener(listener);
				}
			}
		}
	}
	
	private class MyPinger extends Pinger
	{
		private final ServiceLocation location;
		
		public MyPinger(String name, ServiceLocation location) {
			super(name, location);
			this.location=location;
		}

		@Override
		public void failure(String name) {
			delListener(new ThriftListener(location));
		}
		
	}
}
